#include "reg52.h"
#include <intrins.h>  

/*可以针对引脚使用位操作或者port操作，本次实验选择使用位操作*/
/*南北向的红绿灯*/
sbit LED_Red_SN = P1^0;
sbit LED_Yellow_SN = P1^1;
sbit LED_Green_SN = P1^2;

/*东西向的红绿灯*/
sbit LED_Red_EW = P1^3;
sbit LED_Yellow_EW = P1^4;
sbit LED_Green_EW = P1^5;

/*本次倒计时使用的是11.0592MHz的倒计时*/


unsigned char All = 40; //绿-黄-红的一个周期是 40s
unsigned char Red_EW = 20,Red_SN = 20; 
unsigned char Green_EW = 15,Green_SN = 15;
unsigned char Yellow_EW = 5,Yellow_SN = 5;

unsigned char code DuanMa[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char TempData_EW[8]; //存储显示值的全局变量
unsigned char TempData_SN[8]; 

void delay(unsigned int t)
{
 while(--t);
}

sbit SRCLK_SN = P2^0;    //SCK 串行时钟信号
sbit SER_SN = P2^1;			// SER 数据输入口
sbit LATCH_SN = P2^2;   //ST 锁存输出信号

sbit SRCLK_EW = P2^5;    //SCK 串行时钟信号
sbit SER_EW = P2^6;			// SER 数据输入口
sbit LATCH_EW = P2^7;   //ST 锁存输出信号

/*74HC595 主要是控制位码的设置*/


/*配置定时器*/
void Init_Timer0(void)
{
	 TMOD |= 0x01;	                  //使用模式1，16位定时器，使用"|"符号可以在使用多个定时器时不受影响		     
	 TH0 = (65536 - 40680)/256;	      //给定初值，这里使用定时器最大值从0开始计数一直到65535溢出
	 TL0 = (65536 - 40680)%256;
	 EA = 1;            //总中断打开
	 ET0 = 1;           //定时器中断打开
	 TR0 = 1;           //定时器开关打开
}

void SendByte_SN(unsigned char dat)
{
	unsigned char k;
	for(k=0; k<8; k++)
	{
		SRCLK_SN = 0;
		SER_SN = dat&0x80;
		dat <<= 1;
		SRCLK_SN = 1;
	}
}
void SendByte_EW(unsigned char dat)
{
	unsigned char h;
	for(h=0; h<8; h++)
	{
		SRCLK_EW = 0;
		SER_EW = dat&0x80;
		dat <<= 1;
		SRCLK_EW = 1;
	}
}

void Keep_595_SN(void)
{
	LATCH_SN = 1;
	_nop_();
	LATCH_SN = 0;
}

void Keep_595_EW(void)
{
	LATCH_EW = 1;
	_nop_();
	LATCH_EW = 0;
}

void Send2Byte_SN(unsigned char dat1,unsigned char dat2)
{
	SendByte_SN(dat1);
	SendByte_SN(dat2);
}

void Send2Byte_EW(unsigned char dat1,unsigned char dat2)
{
	SendByte_EW(dat1);
	SendByte_EW(dat2);
}

/*显示让它显示的倒计时的时间*/

void SegMent_Display_SN(time)
{
	TempData_SN[0]=DuanMa[time/10];//分解显示信息，如要显示68，则68/10=6  68%10=8  
	TempData_SN[1]=DuanMa[time%10];
	
	Send2Byte_SN(0x01,TempData_SN[0]);
	Keep_595_SN();		
	delay(500);
	Send2Byte_SN(0x02,TempData_SN[1]);
	Keep_595_SN();		
}

/*显示让它显示的倒计时的时间*/

void SegMent_Display_EW(unsigned char time)
{
	TempData_EW[0]=DuanMa[time/10];//分解显示信息，如要显示68，则68/10=6  68%10=8  
	TempData_EW[1]=DuanMa[time%10];
	
	Send2Byte_EW(0x01,TempData_EW[0]);
	Keep_595_EW();		
	delay(500);
	Send2Byte_EW(0x02,TempData_EW[1]);
	Keep_595_EW();		
}

void main()
{
	Init_Timer0();  //打开定时器0
	while(1)	
	{					
		if(All >= 25 && All < 40) //数绿灯的时间 20-40以内
			{
				
				SegMent_Display_SN(Green_SN); //南北方向显示15s倒计时 即时完毕就停止
		
		    SegMent_Display_EW(Red_EW);  //东西方向显示20s倒计时
				
				LED_Green_SN = 0;  //南北向的绿灯亮
				LED_Red_SN = 1;    //南北的红灯不亮 				
							
				LED_Red_EW = 0;    //东西向的红灯亮
				LED_Green_EW = 1;  //东西的绿灯亮	
				
				LED_Yellow_EW = 1;//关闭黄灯闪烁
			}
			
			else if(All >= 20&& All < 25) //黄灯开始闪烁
			{
				SegMent_Display_SN(0); //南北方向暂停显示,东西方向不变
				
				SegMent_Display_EW(Red_EW);
				
				LED_Green_SN = 1;  //南北向的绿灯不亮，黄灯闪烁			
	
			}
			else if(All>= 5 && All < 20)
			{
				SegMent_Display_SN(Red_SN); //南北方向红灯计时
				
				SegMent_Display_EW(Green_EW); //东西方向绿灯灯计时
				
				LED_Green_SN = 1;  //南北向的绿灯不亮
				LED_Red_SN = 0;    //南北向向的红灯亮
				
				
				LED_Red_EW = 1;    //东西向的红灯不亮
				LED_Green_EW = 0;  //东西的绿灯亮	

				LED_Yellow_SN = 1;//关闭黄灯闪烁
				
			}
			else if(All >= 0 && All < 5)
			{				
				SegMent_Display_SN(Red_SN); //红灯倒计时
				
				SegMent_Display_EW(0);		 //黄灯闪烁，暂停读秒	
				
				
				LED_Green_EW = 1;//东西向的绿灯灭
				
			}
	}
		
}

void Timer0_isr(void) interrupt 1 using 1
{
	static unsigned char i;
	TH0 = (65536 - 40680)/256;	     
	TL0 = (65536 - 40680)%256;
	i++;
	
 if(i == 20) //标准的秒级是在20附近
 {
	 i = 0;
	 if(All == 0)		 
			All = 40;//归零就重新赋值
	 else if(All > 0 && All <= 40)
			All--;

		if(Green_SN == 0 )			
			Green_SN = 15;
		else if(Green_EW == 0)	
			Green_EW = 15;		
		else if(Red_SN ==0)
			Red_SN = 20;
		else if(Red_EW == 0)
			Red_EW = 20;
		
		if(All >= 25 && All <40)
		{
			Green_SN --;			
			Red_EW -- ;
		}
	  else if(All >= 20 && All < 25)
		{
			LED_Yellow_SN = ~LED_Yellow_SN; //东西方向的黄色的灯闪烁
			Red_EW -- ;
		}
		else if(All >= 5 && All < 20) //黄灯开始闪烁
		{
			Red_SN --;
			Green_EW --;
		}
		else if(All >= 0 && All < 5)
		{
			Red_SN --;
			LED_Yellow_EW = ~LED_Yellow_EW; //东西方向的黄色的灯闪烁
		}	 
  }
}
